Check how indivisuals cure by surjury.

input data: - /home/rstudio/work/data/ClinicalTable Cell Reports.txt

workflow1: Q1. Is change of body feature (reduce amount of BMI and/or Waist/Hip value …) is correspond to change of the expression profile cluster?

  1. Cluster indivisual by BMI and/or Waist/Hip value … (OB - POB value of body condition)
  2. Cluster indivisual by OB - POB count of insuline responde gene profile.
  3. Compare 1 and 2 cluster with rand index to conclude similality of the cluster.

Problem: Is it OK to just OB - POB count? Need normalization? -> It would be better not to take difference of insuline responde gene profile, but extract insuline response gene in sub group.

Workflow2: 1. Modify table to have 2 column OB vs POB.
2. Check the distribution of OB - POB value of clinic values to get sub groups of the indivisuals. -> better cured vs less cured 3. extract insulin response gene in those sub groups. 4. Check the different insulin response gene between OB sub and POB sub group -> extention of Fig2a.

Q2. Dose 7 enriched TF has same activity ratio though the target? 1. create small directed network of 7 TFs to insuline responde gene. 2. culculate ratio of the target activity (induce, attenuate) 3. Find TF which is commonly enriched but differentry active the targets.

-> This analysis may not be find difference because correlation of the insulin responce gene profile between groups in FigureS2 shows correlation.

library(tidyverse)

Q1

load("~/work/data/ExpressionTables.RData")
clinic <- read_tsv("~/work/data/ClinicalTable Cell Reports.txt")
Rows: 151 Columns: 17── Column specification ───────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr  (4): Patnr, Time, Type, Gender
dbl (13): Age, BMI, Waist, Hip, Syst_BT, Diast_BT, P_glukos, Kol, TG, Ins, HDL, M_v_rde_60_120, cellvol
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

indivisual difference between OB vs POB

pre-preparation

Add W/H value which is also one of the score to varidate obisity.

clinic$wh <- clinic$Waist / clinic$Hip 

get person ID to get match of person.

clinic$ID <- substr(clinic$Patnr, start = 3, stop = nchar(clinic$Patnr))
clinic$Location <- substr(clinic$Patnr, start = 1, stop = 2)

get the sample ID in expression count matrix.


CAGE_ID <- grep("f0", colnames(phase2.female.counts), value=TRUE)
CAGE_ID <- unlist(strsplit(CAGE_ID, "f0"))
CAGE_ID
 [1] "NG1"   "NG2"   "NG3"   "NG4"   "NK13"  "NK14"  "NK15"  "NK22"  "NK25"  "NK26"  "NK27"  "NK29" 
[13] "NK2"   "NK35"  "NK37"  "NK38"  "NK39"  "NK3"   "NK40"  "NK44"  "NK7"   "NK8"   "NK9"   "NO101"
[25] "NO108" "NO117" "NO121" "NO125" "NO131" "NO135" "NO146" "NO150" "NO22"  "NO27"  "NO32"  "NO37" 
[37] "NO40"  "NO47"  "NO48"  "NO50"  "NO51"  "NO56"  "NO68"  "NO73"  "NO77"  "NO89" 

filter Male data, NO group, row with NA data.

filterd <- clinic %>%
  filter(Patnr %in% CAGE_ID) %>% 
  filter(!Gender == "M") %>% 
  filter(Location == "NO") %>% 
  group_by(Type)

This matrix is wide format. It will be more easy to handle long format. Column will be ID, name of the value, value of OB, value of POB, OB - POB.

OB_long <- filter(filterd, Type=="OBESE") %>%
  pivot_longer(cols = c("BMI", "wh", "Syst_BT", "Diast_BT", "P_glukos", "Kol", "TG", "Ins", "HDL", "M_v_rde_60_120", "cellvol"), names_to = "score", values_to = "OB") %>% 
  dplyr::select(!c(Time, Gender,Waist, Hip,Age, Location))

POB_long <- filter(filterd, Type=="POST_OBESE") %>%
  pivot_longer(cols = c("BMI", "wh", "Syst_BT", "Diast_BT", "P_glukos", "Kol", "TG", "Ins", "HDL", "M_v_rde_60_120", "cellvol"), names_to = "score", values_to = "POB") %>% 
 dplyr::select(!c(Time, Gender,Waist, Hip,Age, Location))




merged_matrix <- merge(OB_long, POB_long, by = c("ID", "score", "Patnr"), all = TRUE)
merged_matrix$OB_POB <- merged_matrix$OB - merged_matrix$POB 
merged_matrix$OB_POB_ratio_100 <- merged_matrix$POB / merged_matrix$OB * 100 - 100
merged_matrix$OB_POB_ratio <- log2(merged_matrix$POB / merged_matrix$OB)


head(merged_matrix)

Check parson is N = 23.

length(unique(merged_matrix$ID))
[1] 23

Check which score shows how much difference from OB to POB.

Boxplot of distribution of the score which is difference between OB and POB (OB -POB). Cellvol is high range conpare to other scores.

p <- ggplot(merged_matrix,aes(x=score, y=OB_POB)) +
  geom_boxplot() + 
  geom_point()
#  facet_wrap(~score, ncol=4)
print(p)

Separatery plot ranking bar plot to see the distribution.

p <- ggplot(merged_matrix, aes(x = fct_reorder(score, OB_POB_ratio, .fun = median), y=OB_POB_ratio)) +
  geom_boxplot() + 
  geom_point() +
  labs(title = "Change of clinical status from OB to POB", x="clinical collected scores", y = "log2(POB/OB)")
print(p)

Score which decrease in POB: - cell volume - Insulin level - TG - BMI - Kol

Score which increase in POB: - HDL - M value

POB decrease the scores those un-healthy if it is high score, and increase the scores those healthy if it is high score.

Clinic measurement change

Plot of “Change of clinical status from OB to POB” shows ratio of the change from OB to POB. This plot may not show the importance for the measurement which even small differences are important such as blood pressure. In order to visualize the actual changes, boxplot that relates the corresponding individual data are shown.

longer <- merged_matrix %>% 
  pivot_longer(cols = c("OB", "POB"), names_to = "states", values_to = "value")
longer

#FIXME: better to plot using violine plot.

for (i in unique(longer$score)) { # Loop over loop.vector

  # store data in column.i as x
  sub_df <- longer %>%
    dplyr::filter(score == i)
  
  # Plot histogram of x
  p <- ggplot(sub_df, aes(x = interaction(states, score), y = value)) +
    geom_boxplot(aes(fill = states), alpha = 0.5) +
    geom_line(aes(group = interaction(ID, score)),
            alpha = 0.5, colour = "darkgrey") +
    scale_x_discrete(labels = "") + 
    labs(title = paste0("Change of clinical status from OB to POB: ", i), x="states", y = i)
  
  show(p)
}

ggplot(longer, aes(x = interaction(states, score), y = value)) +
  geom_boxplot(aes(fill = states), alpha = 0.5) +
  geom_line(aes(group = interaction(ID, score)),
            alpha = 0.5, colour = "darkgrey") +
  facet_grid(~score,scales="free_x") +
  scale_x_discrete(labels = "")

Dose those change correlates?

Next see the correlation between those scores.

pob_ob <- pivot_wider(merged_matrix, id_cols = ID, names_from = score, values_from=OB_POB_ratio) %>% 
  drop_na()%>%
  select_if(is.numeric) %>%
  cor()

Diast blood tension and Syst blood tention is highly correlated. BMI and cellvol is correlated, and TG and HDl is negatively correlated. # FIXME: notmalize or standarize.

library(pheatmap)
pheatmap(pob_ob, display_numbers=TRUE)

Dose there subpopulation?

features <- pivot_wider(merged_matrix, id_cols = ID, names_from = score, values_from=OB_POB_ratio) %>% 
  select_if(is.numeric)  %>%
  drop_na()
pca_res <- prcomp(t(features), scale. = TRUE)
pca_res
Standard deviations (1, .., p=11):
 [1] 3.901010e+00 1.475656e+00 9.522736e-01 5.847826e-01 4.015955e-01 3.164272e-01 2.136506e-01
 [8] 1.701989e-01 1.195847e-01 7.379906e-02 1.837866e-16

Rotation (n x k) = (19 x 11):
             PC1         PC2         PC3          PC4         PC5           PC6          PC7         PC8
 [1,] -0.2389693 -0.15706700  0.03367265 -0.456370068  0.08715553  0.0432987246 -0.093424849  0.04023031
 [2,] -0.2526831 -0.10154594  0.04648646  0.054991975 -0.00300070  0.1465249546  0.023961244 -0.01864974
 [3,] -0.2085492  0.28897977 -0.23806437  0.468374508  0.38655026  0.1124163737 -0.289942125 -0.09109109
 [4,] -0.2407646  0.21137860  0.11572953 -0.014183847  0.17118279  0.0039758582  0.275523634  0.03750508
 [5,] -0.2508307  0.01395563  0.03261808  0.240514803  0.16164249 -0.3854093377 -0.194384262  0.12284822
 [6,] -0.2284203 -0.22849317 -0.27973491 -0.071040734 -0.29105045 -0.0008117684 -0.303190414  0.15307950
 [7,] -0.2157009 -0.25819230  0.05065685  0.504417756 -0.54746427  0.2696720866  0.108299591  0.19583769
 [8,] -0.2457352  0.08771806  0.18631173  0.161884311 -0.21337026 -0.3761714322  0.129873508 -0.03517396
 [9,] -0.2349074  0.23602477 -0.16791612 -0.126633629 -0.20040501  0.1030342121  0.020143994  0.01071500
[10,] -0.2254031  0.28634826  0.16132313 -0.226457387 -0.02156809  0.1051722429  0.330484333  0.14967664
[11,] -0.1831216 -0.31516058  0.54379479 -0.094546460  0.01790683 -0.0740666914 -0.052811921 -0.17855184
[12,] -0.2525226 -0.03571501  0.05242185 -0.198682345  0.06661564  0.1056496690 -0.105537329  0.47604956
[13,] -0.2488526  0.07380956 -0.14882375  0.110479305  0.06334065  0.1909859757  0.519920568 -0.29685329
[14,] -0.1493354 -0.45306355 -0.44141169 -0.002864675  0.30280568 -0.3703047293  0.375465579  0.24402211
[15,] -0.2067767 -0.37391986 -0.06248052 -0.044976290  0.27197732  0.4898363202 -0.133342669 -0.32642299
[16,] -0.2371219 -0.08112319  0.35101027  0.130936952  0.14256891 -0.2083489761 -0.048181514 -0.21801628
[17,] -0.2396594  0.07012770 -0.27815604 -0.196951759 -0.28215884 -0.3119598629 -0.209314341 -0.48370286
[18,] -0.2344084  0.23853044 -0.15329916 -0.199103260 -0.14064195  0.0370589531 -0.006196166 -0.06996915
[19,] -0.2381066  0.22986006  0.11128983  0.006507977  0.15102091  0.0852406102 -0.271320914  0.29761913
              PC9        PC10          PC11
 [1,] -0.39593127 -0.40447908  0.4812431088
 [2,]  0.14740218 -0.27502337 -0.4767519006
 [3,] -0.10838645 -0.21944941  0.1747766435
 [4,]  0.06784204 -0.09299340 -0.1268098289
 [5,] -0.07654583  0.09381908 -0.1115586616
 [6,] -0.23941379 -0.21973989 -0.3789963384
 [7,]  0.09613289 -0.10620697  0.3033058307
 [8,] -0.28233197  0.27285888 -0.0192654412
 [9,]  0.07120092  0.21884948  0.3170117386
[10,]  0.09645009 -0.18891100 -0.0005117691
[11,] -0.19131590  0.04378103 -0.1195697618
[12,]  0.23404931  0.45604815  0.0293430140
[13,] -0.38607618  0.16536115 -0.0995236966
[14,]  0.13738157 -0.02920401  0.0804678906
[15,]  0.12060623  0.32763441 -0.0215555168
[16,]  0.46347625 -0.21267854  0.2264762873
[17,]  0.14357544  0.16259950  0.0899823001
[18,]  0.31111602 -0.19164600 -0.2280054930
[19,] -0.18051321  0.15399313 -0.0464949834

it is hard to say there is a sub-group in 23 (19 after drop na) individual. #FIXME: Check contribution

library(ggfortify)
autoplot(pca_res, data = t(features))

create subgroup

  • cell volume
  • Insuline
  • M-value
get_sorted <- function(df, feature){
  base <- df %>% filter(score == feature) %>% 
    drop_na() %>%
    arrange(OB_POB_ratio)
    
  return(base)
  
}

n = 7
CV <- get_sorted(merged_matrix, "cellvol")
CV_head <- head(CV, n)
CV_tail <- tail(CV, n)
Ins <- get_sorted(merged_matrix, "Ins")
Ins_head <- head(Ins, n)
Ins_tail <- tail(Ins, n)
MV <- get_sorted(merged_matrix, "M_v_rde_60_120")
MV_head <- head(MV, n)
MV_tail <- tail(MV, n)

Is there overlap between groups?

Change of those values are different in individual. This infomation is also able to assumed by correlation result. Those scores has less correlated means, change of scores are different amoung individuals.

library(ggVennDiagram)
x <- list(CV_cure=CV_head$Patnr, Ins_cure=Ins_head$Patnr, MV_cure=MV_tail$Patnr)
ggVennDiagram(x, show_intersect=TRUE)
Warning: Ignoring unknown aesthetics: text
x <- list(CV_less=CV_tail$Patnr, Ins_less=Ins_tail$Patnr, MV_less=MV_head$Patnr)
ggVennDiagram(x, show_intersect=TRUE)
Warning: Ignoring unknown aesthetics: text

Insuline responde gene of those subgroup.

Insuline respond subgroup based on Insuline level.

cols_to_select <- Ins_head$Patnr
selected_cols <- phase2.female.counts %>%
  dplyr::select(contains(cols_to_select))

selected_cols
load("/home/rstudio/work/data/ExpressionTables.RData")
load("/home/rstudio/work/data/Annotation.RData")
load("/home/rstudio/work/data/Cohort.RData")

cohort_2 <- cohort %>%
  dplyr::filter(Patnr %in% cols_to_select)
library(edgeR)
##################################
# DE analysis of paired samples
###################################
cohort <- cohort_2

IDs<-paste(cohort$OB_NO,as.factor(cohort$IDs),sep=".")
Condition<-cohort$newcond2

# deviding expression matrix to subgroup
df.pairs <- selected_cols

# DE Analysis
y <- DGEList(counts=df.pairs,group = Condition)
y
design <- model.matrix(~0+Condition+IDs,data=y$samples)
design <- design[,!grepl("f0", colnames(design))]
design <- design[, colSums(design != 0) > 0]
colnames(design)<-make.names(colnames(design))
y <- calcNormFactors(y,norm.method="RLE")
y <- estimateDisp(y,design)
fit <- glmFit(y,design,robust=T)

my.contrasts<-makeContrasts(
  HivsF.OB=ConditionOBESE.h0,
  HivsF.POB=ConditionOBESE.h2-ConditionOBESE.f2,
  levels=design)
contrasts<-colnames(my.contrasts)
myfun <- function(filex) {
  print(filex)
  lrt <- glmLRT(fit, contrast=my.contrasts[,filex])
  out.top=topTags(lrt,n=Inf,adjust.method='BH')
  out.adj=out.top$table
  out.adj.1<-out.adj
  if(nrow(out.adj.1)==0){
    return()
  }else{
    out.adj.1$Contrast<-filex
    out.adj.1$TC<-rownames(out.adj.1)
    out.adj.1$updown<-ifelse(out.adj.1$logFC>0,"up","down")
    return(out.adj.1)
  }
}
y.list<-(lapply(contrasts, myfun))
tab<-do.call(rbind, y.list)
tab$Sign<-ifelse(tab$FDR<0.05,"sign","no")
res.count <- table(tab[tab$Sign=="sign",]$Contrast,tab[tab$Sign=="sign",]$updown )
res.count 

Chage the design

edgeR result before has 441 down regulated gene. This is not seems right. It is because design matrix is not propary setted.

What I want to see is different insuline response gene between + group (well cured) and - group (mild cured). It means, POB is not one but separated to 2.

  • OB (n=6): OB_f vs OB_hi
  • POB+ (n=6): POB+_f vs POB+_hi
  • POB- (n=6): POB-_f vs POB-_hi
  • NO (n=6): NO_f vs NO_hi

NO will be also matched with Age, M-value and BMI mean of POB+ and POB-.

Age_df <- data.frame(POBp = POBp$Age, POBm = POBm$Age)
ggplot(data = Age_df) +
  geom_point()
Error in `geom_point()`:
! Problem while setting up geom.
ℹ Error occurred in the 1st layer.
Caused by error in `compute_geom_1()`:
! `geom_point()` requires the following missing aesthetics: x and y
Backtrace:
  1. base (local) `<fn>`(x)
  2. ggplot2:::print.ggplot(x)
  4. ggplot2:::ggplot_build.ggplot(x)
  5. ggplot2:::by_layer(...)
 12. ggplot2 (local) f(l = layers[[i]], d = data[[i]])
 13. l$compute_geom_1(d)
 14. ggplot2 (local) compute_geom_1(..., self = self)

First get matched NO groups.

# get NO with matched distribution with POB+ and POB-
set.seed(123)
load("/home/rstudio/work/data/Cohort.RData")

POBp <- clinic %>% 
    dplyr::filter(Patnr %in% Ins_head$Patnr)
  
POBm <- clinic %>% 
    dplyr::filter(Patnr %in% Ins_tail$Patnr)
  
NOs <- clinic %>% dplyr::filter(Type =="NO")
select_NO <- NOs %>%
    dplyr::filter(max(POBp$Age) > Age,  Age> min(POBp$Age)) %>%
    dplyr::filter(max(POBp$BMI) > BMI,  BMI> min(POBp$BMI)) %>%
    dplyr::filter(max(POBp$M_v_rde_60_120) > M_v_rde_60_120,  M_v_rde_60_120> min(POBp$M_v_rde_60_120)) %>%
    dplyr::filter(Patnr %in% cohort$Patnr) %>%
    sample_n(7)

Also select 6 of OB (each 3 from POB+, POB- matched OB).


OBp_ID <- sample(Ins_head$Patnr, 4)
OBm_ID <- sample(Ins_tail$Patnr, 3)
OB_ID <- c(OBp_ID, OBm_ID)
# Data to run edgeR
print(OB_ID) # OB group
[1] "NO51"  "NO22"  "NO27"  "NO77"  "NO101" "NO48"  "NO146"
print(select_NO$Patnr) # NO group
[1] "NG3"  "NK8"  "NK35" "NG2"  "NK26" "NK7"  "NK25"
print(Ins_head$Patnr) # POB+ group
[1] "NO27"  "NO73"  "NO51"  "NO77"  "NO117" "NO135" "NO22" 
print(Ins_tail$Patnr) # POB- group
[1] "NO101" "NO89"  "NO32"  "NO131" "NO146" "NO50"  "NO48" 
# column names in the count matrix
OB_col <- cohort %>%
  dplyr::filter(OB_NO_POB == "OB") %>%
  dplyr::filter(Patnr %in% OB_ID) %>%
  select(Cond)


NO_col <- cohort %>%
  dplyr::filter(OB_NO_POB == "NO") %>%
  dplyr::filter(Patnr %in% select_NO$Patnr) %>%
  select(Cond)

POBp_col <- cohort %>%
  dplyr::filter(OB_NO_POB == "POB") %>%
  dplyr::filter(Patnr %in% Ins_head$Patnr) %>%
  select(Cond)


POBm_col <- cohort %>%
  dplyr::filter(OB_NO_POB == "POB") %>%
  dplyr::filter(Patnr %in% Ins_tail$Patnr) %>%
  select(Cond)
select_sample <- c(OB_col$Cond, NO_col$Cond, POBp_col$Cond, POBm_col$Cond)
# select samples to use
df.pairs <- phase2.female.counts %>% 
     dplyr::select(contains(select_sample))


load("/home/rstudio/work/data/Cohort.RData")
# subset cohort file
cohort_2 <- cohort %>%
  dplyr::filter(Cond %in% select_sample)

cohort <- cohort_2
cohort$condition <- ifelse(cohort$Cond %in% OB_col$Cond, "OB", 
                           ifelse(cohort$Cond %in% NO_col$Cond, "NO", 
                                  ifelse(cohort$Cond %in% POBp_col$Cond, "POBp",
                                         ifelse(cohort$Cond %in% POBm_col$Cond, "POBm","NA"))))

cohort <- cohort %>% 
  mutate(time = str_sub(Cond,-2,-1))
cohort <- cohort %>% 
  mutate(condition2 = paste(cohort$condition, cohort$time,sep="."))

IDs<-paste(cohort$OB_NO,as.factor(cohort$IDs),sep=".") # put same ID for same indivisual
Condition<-cohort$condition2
# DE Analysis
y <- DGEList(counts=df.pairs,group = Condition)
# design: Condition (OB,NO,POBp,POBm) and indivisual
design<-model.matrix(~0+Condition+IDs,data=y$samples)
design <- design[,!grepl("f0", colnames(design))]
#design <- design[,!grepl("NO.f", colnames(design))]
#design<-design[, colSums(design != 0) > 0]
colnames(design)<-make.names(colnames(design))
y <- calcNormFactors(y,norm.method="RLE")
y <- estimateDisp(y,design)
fit <- glmFit(y,design,robust=T)
my.contrasts<-makeContrasts(
  HivsF.NO=ConditionNO.h0,
  HivsF.OB=ConditionOB.h0,
  HivsF.POBp=ConditionPOBp.h2-ConditionPOBp.f2,
  HivsF.POBm=ConditionPOBm.h2-ConditionPOBm.f2,
  levels=design)

contrasts<-colnames(my.contrasts)
myfun <- function(filex) {
  print(filex)
  lrt <- glmLRT(fit, contrast=my.contrasts[,filex])
  out.top=topTags(lrt,n=Inf,adjust.method='BH')
  out.adj=out.top$table
  out.adj.1<-out.adj
  if(nrow(out.adj.1)==0){
    return()
  }else{
    out.adj.1$Contrast<-filex
    out.adj.1$TC<-rownames(out.adj.1)
    out.adj.1$updown<-ifelse(out.adj.1$logFC>0,"up","down")
    return(out.adj.1)
  }
}

y.list<-(lapply(contrasts, myfun))
[1] "HivsF.NO"
[1] "HivsF.OB"
[1] "HivsF.POBp"
[1] "HivsF.POBm"
tab<-do.call(rbind, y.list)
tab$Sign<-ifelse(tab$FDR<0.05,"sign","no")
res.count <- table(tab[tab$Sign=="sign",]$Contrast,tab[tab$Sign=="sign",]$updown )
res.count 
            
             down  up
  HivsF.NO    472   0
  HivsF.OB      3   0
  HivsF.POBm    0   1
save(tab,file="/home/rstudio/work/data/OB7_NO7_POBp7_POBm7.RData")

Remove NO

select_sample <- c(OB_col$Cond, POBp_col$Cond, POBm_col$Cond)
# select samples to use
df.pairs <- phase2.female.counts %>% 
     dplyr::select(contains(select_sample))


load("/home/rstudio/work/data/Cohort.RData")
# subset cohort file
cohort_2 <- cohort %>%
  dplyr::filter(Cond %in% select_sample)

cohort <- cohort_2
cohort$condition <- ifelse(cohort$Cond %in% OB_col$Cond, "OB", 
                                  ifelse(cohort$Cond %in% POBp_col$Cond, "POBp",
                                         ifelse(cohort$Cond %in% POBm_col$Cond, "POBm","NA")))

cohort <- cohort %>% 
  mutate(time = str_sub(Cond,-2,-1))
cohort <- cohort %>% 
  mutate(condition2 = paste(cohort$condition, cohort$time,sep="."))

IDs<-paste(cohort$OB_NO,as.factor(cohort$IDs),sep=".") # put same ID for same indivisual
Condition<-cohort$condition2


y <- DGEList(counts=df.pairs,group = Condition)
design<-model.matrix(~0+Condition+IDs,data=y$samples)
design <- design[,!grepl("f0", colnames(design))]
design<-design[, colSums(design != 0) > 0]
colnames(design)<-make.names(colnames(design))
y <- calcNormFactors(y,norm.method="RLE")

y <- estimateDisp(y,design)
fit <- glmFit(y,design,robust=T)

my.contrasts<-makeContrasts(
  HivsF.OB=ConditionOB.h0,
  HivsF.POBp=ConditionPOBp.h2-ConditionPOBp.f2,
  HivsF.POBm=ConditionPOBm.h2-ConditionPOBm.f2,
  levels=design)

contrasts<-colnames(my.contrasts)
myfun <- function(filex) {
  print(filex)
  lrt <- glmLRT(fit, contrast=my.contrasts[,filex])
  out.top=topTags(lrt,n=Inf,adjust.method='BH')
  out.adj=out.top$table
  out.adj.1<-out.adj
  if(nrow(out.adj.1)==0){
    return()
  }else{
    out.adj.1$Contrast<-filex
    out.adj.1$TC<-rownames(out.adj.1)
    out.adj.1$updown<-ifelse(out.adj.1$logFC>0,"up","down")
    return(out.adj.1)
  }
}

y.list<-(lapply(contrasts, myfun))
[1] "HivsF.OB"
[1] "HivsF.POBp"
[1] "HivsF.POBm"
tab<-do.call(rbind, y.list)
tab$Sign<-ifelse(tab$FDR<0.05,"sign","no")
res.count <- table(tab[tab$Sign=="sign",]$Contrast,tab[tab$Sign=="sign",]$updown )
res.count 
            
             down  up
  HivsF.OB    678  51
  HivsF.POBm    5   0
  HivsF.POBp    3   0
save(tab,file="/home/rstudio/work/data/OB6_POBp6_POBm6.RData")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIENoZWNrIGhvdyBpbmRpdmlzdWFscyBjdXJlIGJ5IHN1cmp1cnkuCgppbnB1dCBkYXRhOiAKLSAvaG9tZS9yc3R1ZGlvL3dvcmsvZGF0YS9DbGluaWNhbFRhYmxlIENlbGwgUmVwb3J0cy50eHQKCndvcmtmbG93MToKUTEuIElzIGNoYW5nZSBvZiBib2R5IGZlYXR1cmUgKHJlZHVjZSBhbW91bnQgb2YgQk1JIGFuZC9vciBXYWlzdC9IaXAgdmFsdWUgLi4uKSBpcyBjb3JyZXNwb25kIHRvIGNoYW5nZSBvZiB0aGUgZXhwcmVzc2lvbiBwcm9maWxlIGNsdXN0ZXI/CgoxLiBDbHVzdGVyIGluZGl2aXN1YWwgYnkgQk1JIGFuZC9vciBXYWlzdC9IaXAgdmFsdWUgLi4uIChPQiAtIFBPQiB2YWx1ZSBvZiBib2R5IGNvbmRpdGlvbikKMi4gQ2x1c3RlciBpbmRpdmlzdWFsIGJ5IE9CIC0gUE9CIGNvdW50IG9mIGluc3VsaW5lIHJlc3BvbmRlIGdlbmUgcHJvZmlsZS4KMy4gQ29tcGFyZSAxIGFuZCAyIGNsdXN0ZXIgd2l0aCByYW5kIGluZGV4IHRvIGNvbmNsdWRlIHNpbWlsYWxpdHkgb2YgdGhlIGNsdXN0ZXIuCgpQcm9ibGVtOiBJcyBpdCBPSyB0byBqdXN0IE9CIC0gUE9CIGNvdW50PyBOZWVkIG5vcm1hbGl6YXRpb24/Ci0+IEl0IHdvdWxkIGJlIGJldHRlciBub3QgdG8gdGFrZSBkaWZmZXJlbmNlIG9mIGluc3VsaW5lIHJlc3BvbmRlIGdlbmUgcHJvZmlsZSwgYnV0IGV4dHJhY3QgaW5zdWxpbmUgcmVzcG9uc2UgZ2VuZSBpbiBzdWIgZ3JvdXAuCgpXb3JrZmxvdzI6CjEuIE1vZGlmeSB0YWJsZSB0byBoYXZlIDIgY29sdW1uIE9CIHZzIFBPQi4gIAoyLiBDaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIE9CIC0gUE9CIHZhbHVlIG9mIGNsaW5pYyB2YWx1ZXMgdG8gZ2V0IHN1YiBncm91cHMgb2YgdGhlIGluZGl2aXN1YWxzLiAtPiBiZXR0ZXIgY3VyZWQgdnMgbGVzcyBjdXJlZAozLiBleHRyYWN0IGluc3VsaW4gcmVzcG9uc2UgZ2VuZSBpbiB0aG9zZSBzdWIgZ3JvdXBzLgo0LiBDaGVjayB0aGUgZGlmZmVyZW50IGluc3VsaW4gcmVzcG9uc2UgZ2VuZSBiZXR3ZWVuIE9CIHN1YiBhbmQgUE9CIHN1YiBncm91cCAtPiBleHRlbnRpb24gb2YgRmlnMmEuCgpRMi4gRG9zZSA3IGVucmljaGVkIFRGIGhhcyBzYW1lIGFjdGl2aXR5IHJhdGlvIHRob3VnaCB0aGUgdGFyZ2V0PwoxLiBjcmVhdGUgc21hbGwgZGlyZWN0ZWQgbmV0d29yayBvZiA3IFRGcyB0byBpbnN1bGluZSByZXNwb25kZSBnZW5lLgoyLiBjdWxjdWxhdGUgcmF0aW8gb2YgdGhlIHRhcmdldCBhY3Rpdml0eSAoaW5kdWNlLCBhdHRlbnVhdGUpCjMuIEZpbmQgVEYgd2hpY2ggaXMgY29tbW9ubHkgZW5yaWNoZWQgYnV0IGRpZmZlcmVudHJ5IGFjdGl2ZSB0aGUgdGFyZ2V0cy4KCi0+IFRoaXMgYW5hbHlzaXMgbWF5IG5vdCBiZSBmaW5kIGRpZmZlcmVuY2UgYmVjYXVzZSBjb3JyZWxhdGlvbiBvZiB0aGUgaW5zdWxpbiByZXNwb25jZSBnZW5lIHByb2ZpbGUgYmV0d2VlbiBncm91cHMgaW4gRmlndXJlUzIgc2hvd3MgY29ycmVsYXRpb24uCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyBRMQpgYGB7cn0KbG9hZCgifi93b3JrL2RhdGEvRXhwcmVzc2lvblRhYmxlcy5SRGF0YSIpCmNsaW5pYyA8LSByZWFkX3Rzdigifi93b3JrL2RhdGEvQ2xpbmljYWxUYWJsZSBDZWxsIFJlcG9ydHMudHh0IikKYGBgCgojIyBpbmRpdmlzdWFsIGRpZmZlcmVuY2UgYmV0d2VlbiBPQiB2cyBQT0IKIyMjIHByZS1wcmVwYXJhdGlvbgoKQWRkIFcvSCB2YWx1ZSB3aGljaCBpcyBhbHNvIG9uZSBvZiB0aGUgc2NvcmUgdG8gdmFyaWRhdGUgb2Jpc2l0eS4KYGBge3J9CmNsaW5pYyR3aCA8LSBjbGluaWMkV2Fpc3QgLyBjbGluaWMkSGlwIApgYGAKCmdldCBwZXJzb24gSUQgdG8gZ2V0IG1hdGNoIG9mIHBlcnNvbi4KYGBge3J9CmNsaW5pYyRJRCA8LSBzdWJzdHIoY2xpbmljJFBhdG5yLCBzdGFydCA9IDMsIHN0b3AgPSBuY2hhcihjbGluaWMkUGF0bnIpKQpjbGluaWMkTG9jYXRpb24gPC0gc3Vic3RyKGNsaW5pYyRQYXRuciwgc3RhcnQgPSAxLCBzdG9wID0gMikKYGBgCgpnZXQgdGhlIHNhbXBsZSBJRCBpbiBleHByZXNzaW9uIGNvdW50IG1hdHJpeC4KYGBge3J9CgpDQUdFX0lEIDwtIGdyZXAoImYwIiwgY29sbmFtZXMocGhhc2UyLmZlbWFsZS5jb3VudHMpLCB2YWx1ZT1UUlVFKQpDQUdFX0lEIDwtIHVubGlzdChzdHJzcGxpdChDQUdFX0lELCAiZjAiKSkKQ0FHRV9JRApgYGAKCmZpbHRlciBNYWxlIGRhdGEsIE5PIGdyb3VwLCByb3cgd2l0aCBOQSBkYXRhLgpgYGB7cn0KZmlsdGVyZCA8LSBjbGluaWMgJT4lCiAgZmlsdGVyKFBhdG5yICVpbiUgQ0FHRV9JRCkgJT4lIAogIGZpbHRlcighR2VuZGVyID09ICJNIikgJT4lIAogIGZpbHRlcihMb2NhdGlvbiA9PSAiTk8iKSAlPiUgCiAgZ3JvdXBfYnkoVHlwZSkKYGBgCgpUaGlzIG1hdHJpeCBpcyB3aWRlIGZvcm1hdC4gSXQgd2lsbCBiZSBtb3JlIGVhc3kgdG8gaGFuZGxlIGxvbmcgZm9ybWF0LiAKQ29sdW1uIHdpbGwgYmUgSUQsIG5hbWUgb2YgdGhlIHZhbHVlLCB2YWx1ZSBvZiBPQiwgdmFsdWUgb2YgUE9CLCBPQiAtIFBPQi4KYGBge3J9Ck9CX2xvbmcgPC0gZmlsdGVyKGZpbHRlcmQsIFR5cGU9PSJPQkVTRSIpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiQk1JIiwgIndoIiwgIlN5c3RfQlQiLCAiRGlhc3RfQlQiLCAiUF9nbHVrb3MiLCAiS29sIiwgIlRHIiwgIklucyIsICJIREwiLCAiTV92X3JkZV82MF8xMjAiLCAiY2VsbHZvbCIpLCBuYW1lc190byA9ICJzY29yZSIsIHZhbHVlc190byA9ICJPQiIpICU+JSAKICBkcGx5cjo6c2VsZWN0KCFjKFRpbWUsIEdlbmRlcixXYWlzdCwgSGlwLEFnZSwgTG9jYXRpb24pKQoKUE9CX2xvbmcgPC0gZmlsdGVyKGZpbHRlcmQsIFR5cGU9PSJQT1NUX09CRVNFIikgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJCTUkiLCAid2giLCAiU3lzdF9CVCIsICJEaWFzdF9CVCIsICJQX2dsdWtvcyIsICJLb2wiLCAiVEciLCAiSW5zIiwgIkhETCIsICJNX3ZfcmRlXzYwXzEyMCIsICJjZWxsdm9sIiksIG5hbWVzX3RvID0gInNjb3JlIiwgdmFsdWVzX3RvID0gIlBPQiIpICU+JSAKIGRwbHlyOjpzZWxlY3QoIWMoVGltZSwgR2VuZGVyLFdhaXN0LCBIaXAsQWdlLCBMb2NhdGlvbikpCgoKCgptZXJnZWRfbWF0cml4IDwtIG1lcmdlKE9CX2xvbmcsIFBPQl9sb25nLCBieSA9IGMoIklEIiwgInNjb3JlIiwgIlBhdG5yIiksIGFsbCA9IFRSVUUpCm1lcmdlZF9tYXRyaXgkT0JfUE9CIDwtIG1lcmdlZF9tYXRyaXgkT0IgLSBtZXJnZWRfbWF0cml4JFBPQiAKbWVyZ2VkX21hdHJpeCRPQl9QT0JfcmF0aW9fMTAwIDwtIG1lcmdlZF9tYXRyaXgkUE9CIC8gbWVyZ2VkX21hdHJpeCRPQiAqIDEwMCAtIDEwMAptZXJnZWRfbWF0cml4JE9CX1BPQl9yYXRpbyA8LSBsb2cyKG1lcmdlZF9tYXRyaXgkUE9CIC8gbWVyZ2VkX21hdHJpeCRPQikKCgpoZWFkKG1lcmdlZF9tYXRyaXgpCmBgYAoKCkNoZWNrIHBhcnNvbiBpcyBOID0gMjMuCmBgYHtyfQpsZW5ndGgodW5pcXVlKG1lcmdlZF9tYXRyaXgkSUQpKQpgYGAKCiMjIyBDaGVjayB3aGljaCBzY29yZSBzaG93cyBob3cgbXVjaCBkaWZmZXJlbmNlIGZyb20gT0IgdG8gUE9CLgoKQm94cGxvdCBvZiBkaXN0cmlidXRpb24gb2YgdGhlIHNjb3JlIHdoaWNoIGlzIGRpZmZlcmVuY2UgYmV0d2VlbiBPQiBhbmQgUE9CIChPQiAtUE9CKS4gQ2VsbHZvbCBpcyBoaWdoIHJhbmdlIGNvbnBhcmUgdG8gb3RoZXIgc2NvcmVzLgpgYGB7cn0KcCA8LSBnZ3Bsb3QobWVyZ2VkX21hdHJpeCxhZXMoeD1zY29yZSwgeT1PQl9QT0IpKSArCiAgZ2VvbV9ib3hwbG90KCkgKyAKICBnZW9tX3BvaW50KCkKIyAgZmFjZXRfd3JhcCh+c2NvcmUsIG5jb2w9NCkKcHJpbnQocCkKYGBgCgpTZXBhcmF0ZXJ5IHBsb3QgcmFua2luZyBiYXIgcGxvdCB0byBzZWUgdGhlIGRpc3RyaWJ1dGlvbi4KYGBge3J9CnAgPC0gZ2dwbG90KG1lcmdlZF9tYXRyaXgsIGFlcyh4ID0gZmN0X3Jlb3JkZXIoc2NvcmUsIE9CX1BPQl9yYXRpbywgLmZ1biA9IG1lZGlhbiksIHk9T0JfUE9CX3JhdGlvKSkgKwogIGdlb21fYm94cGxvdCgpICsgCiAgZ2VvbV9wb2ludCgpICsKICBsYWJzKHRpdGxlID0gIkNoYW5nZSBvZiBjbGluaWNhbCBzdGF0dXMgZnJvbSBPQiB0byBQT0IiLCB4PSJjbGluaWNhbCBjb2xsZWN0ZWQgc2NvcmVzIiwgeSA9ICJsb2cyKFBPQi9PQikiKQpwcmludChwKQpgYGAKClNjb3JlIHdoaWNoIGRlY3JlYXNlIGluIFBPQjoKLSBjZWxsIHZvbHVtZSAKLSBJbnN1bGluIGxldmVsCi0gVEcgCi0gQk1JCi0gS29sCiAKU2NvcmUgd2hpY2ggaW5jcmVhc2UgaW4gUE9COgotIEhETAotIE0gdmFsdWUKClBPQiBkZWNyZWFzZSB0aGUgc2NvcmVzIHRob3NlIHVuLWhlYWx0aHkgaWYgaXQgaXMgaGlnaCBzY29yZSwgYW5kIGluY3JlYXNlIHRoZSBzY29yZXMgdGhvc2UgaGVhbHRoeSBpZiBpdCBpcyBoaWdoIHNjb3JlLgoKIyMjIENsaW5pYyBtZWFzdXJlbWVudCBjaGFuZ2UKUGxvdCBvZiAiQ2hhbmdlIG9mIGNsaW5pY2FsIHN0YXR1cyBmcm9tIE9CIHRvIFBPQiIgc2hvd3MgcmF0aW8gb2YgdGhlIGNoYW5nZSBmcm9tIE9CIHRvIFBPQi4gVGhpcyBwbG90IG1heSBub3Qgc2hvdyB0aGUgaW1wb3J0YW5jZSBmb3IgdGhlIG1lYXN1cmVtZW50IHdoaWNoIGV2ZW4gc21hbGwgZGlmZmVyZW5jZXMgYXJlIGltcG9ydGFudCBzdWNoIGFzIGJsb29kIHByZXNzdXJlLiBJbiBvcmRlciB0byB2aXN1YWxpemUgdGhlIGFjdHVhbCBjaGFuZ2VzLCBib3hwbG90IHRoYXQgcmVsYXRlcyB0aGUgY29ycmVzcG9uZGluZyBpbmRpdmlkdWFsIGRhdGEgYXJlIHNob3duLgoKCgpgYGB7cn0KbG9uZ2VyIDwtIG1lcmdlZF9tYXRyaXggJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYygiT0IiLCAiUE9CIiksIG5hbWVzX3RvID0gInN0YXRlcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpCmxvbmdlcgpgYGAKCgojRklYTUU6IApiZXR0ZXIgdG8gcGxvdCB1c2luZyB2aW9saW5lIHBsb3QuCgoKYGBge3J9CmZvciAoaSBpbiB1bmlxdWUobG9uZ2VyJHNjb3JlKSkgeyAjIExvb3Agb3ZlciBsb29wLnZlY3RvcgoKICAjIHN0b3JlIGRhdGEgaW4gY29sdW1uLmkgYXMgeAogIHN1Yl9kZiA8LSBsb25nZXIgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKHNjb3JlID09IGkpCiAgCiAgIyBQbG90IGhpc3RvZ3JhbSBvZiB4CiAgcCA8LSBnZ3Bsb3Qoc3ViX2RmLCBhZXMoeCA9IGludGVyYWN0aW9uKHN0YXRlcywgc2NvcmUpLCB5ID0gdmFsdWUpKSArCiAgICBnZW9tX2JveHBsb3QoYWVzKGZpbGwgPSBzdGF0ZXMpLCBhbHBoYSA9IDAuNSkgKwogICAgZ2VvbV9saW5lKGFlcyhncm91cCA9IGludGVyYWN0aW9uKElELCBzY29yZSkpLAogICAgICAgICAgICBhbHBoYSA9IDAuNSwgY29sb3VyID0gImRhcmtncmV5IikgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSAiIikgKyAKICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoIkNoYW5nZSBvZiBjbGluaWNhbCBzdGF0dXMgZnJvbSBPQiB0byBQT0I6ICIsIGkpLCB4PSJzdGF0ZXMiLCB5ID0gaSkKICAKICBzaG93KHApCn0KYGBgCgoKYGBge3J9CmdncGxvdChsb25nZXIsIGFlcyh4ID0gaW50ZXJhY3Rpb24oc3RhdGVzLCBzY29yZSksIHkgPSB2YWx1ZSkpICsKICBnZW9tX2JveHBsb3QoYWVzKGZpbGwgPSBzdGF0ZXMpLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBpbnRlcmFjdGlvbihJRCwgc2NvcmUpKSwKICAgICAgICAgICAgYWxwaGEgPSAwLjUsIGNvbG91ciA9ICJkYXJrZ3JleSIpICsKICBmYWNldF9ncmlkKH5zY29yZSxzY2FsZXM9ImZyZWVfeCIpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9ICIiKQpgYGAKCiMjIyBEb3NlIHRob3NlIGNoYW5nZSBjb3JyZWxhdGVzPwoKTmV4dCBzZWUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhvc2Ugc2NvcmVzLgoKYGBge3J9CnBvYl9vYiA8LSBwaXZvdF93aWRlcihtZXJnZWRfbWF0cml4LCBpZF9jb2xzID0gSUQsIG5hbWVzX2Zyb20gPSBzY29yZSwgdmFsdWVzX2Zyb209T0JfUE9CX3JhdGlvKSAlPiUgCiAgZHJvcF9uYSgpJT4lCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JQogIGNvcigpCmBgYAoKRGlhc3QgYmxvb2QgdGVuc2lvbiBhbmQgU3lzdCBibG9vZCB0ZW50aW9uIGlzIGhpZ2hseSBjb3JyZWxhdGVkLiBCTUkgYW5kIGNlbGx2b2wgaXMgY29ycmVsYXRlZCwgYW5kIFRHIGFuZCBIRGwgaXMgbmVnYXRpdmVseSBjb3JyZWxhdGVkLgojIEZJWE1FOgpub3RtYWxpemUgb3Igc3RhbmRhcml6ZS4KCmBgYHtyfQpsaWJyYXJ5KHBoZWF0bWFwKQpwaGVhdG1hcChwb2Jfb2IsIGRpc3BsYXlfbnVtYmVycz1UUlVFKQpgYGAKCiMgRG9zZSB0aGVyZSBzdWJwb3B1bGF0aW9uPwoKYGBge3J9CmZlYXR1cmVzIDwtIHBpdm90X3dpZGVyKG1lcmdlZF9tYXRyaXgsIGlkX2NvbHMgPSBJRCwgbmFtZXNfZnJvbSA9IHNjb3JlLCB2YWx1ZXNfZnJvbT1PQl9QT0JfcmF0aW8pICU+JSAKICBzZWxlY3RfaWYoaXMubnVtZXJpYykgICU+JQogIGRyb3BfbmEoKQpgYGAKCgpgYGB7cn0KcGNhX3JlcyA8LSBwcmNvbXAodChmZWF0dXJlcyksIHNjYWxlLiA9IFRSVUUpCnBjYV9yZXMKYGBgCgppdCBpcyBoYXJkIHRvIHNheSB0aGVyZSBpcyBhIHN1Yi1ncm91cCBpbiAyMyAoMTkgYWZ0ZXIgZHJvcCBuYSkgaW5kaXZpZHVhbC4KI0ZJWE1FOiBDaGVjayBjb250cmlidXRpb24KCmBgYHtyfQpsaWJyYXJ5KGdnZm9ydGlmeSkKYXV0b3Bsb3QocGNhX3JlcywgZGF0YSA9IHQoZmVhdHVyZXMpKQpgYGAKCgojIyMgY3JlYXRlIHN1Ymdyb3VwCi0gY2VsbCB2b2x1bWUKLSBJbnN1bGluZQotIE0tdmFsdWUKCgpgYGB7cn0KZ2V0X3NvcnRlZCA8LSBmdW5jdGlvbihkZiwgZmVhdHVyZSl7CiAgYmFzZSA8LSBkZiAlPiUgZmlsdGVyKHNjb3JlID09IGZlYXR1cmUpICU+JSAKICAgIGRyb3BfbmEoKSAlPiUKICAgIGFycmFuZ2UoT0JfUE9CX3JhdGlvKQogICAgCiAgcmV0dXJuKGJhc2UpCiAgCn0KCm4gPSA2CmBgYAoKCmBgYHtyfQpDViA8LSBnZXRfc29ydGVkKG1lcmdlZF9tYXRyaXgsICJjZWxsdm9sIikKQ1ZfaGVhZCA8LSBoZWFkKENWLCBuKQpDVl90YWlsIDwtIHRhaWwoQ1YsIG4pCmBgYAoKYGBge3J9CklucyA8LSBnZXRfc29ydGVkKG1lcmdlZF9tYXRyaXgsICJJbnMiKQpJbnNfaGVhZCA8LSBoZWFkKElucywgbikKSW5zX3RhaWwgPC0gdGFpbChJbnMsIG4pCmBgYAoKYGBge3J9Ck1WIDwtIGdldF9zb3J0ZWQobWVyZ2VkX21hdHJpeCwgIk1fdl9yZGVfNjBfMTIwIikKTVZfaGVhZCA8LSBoZWFkKE1WLCBuKQpNVl90YWlsIDwtIHRhaWwoTVYsIG4pCmBgYAoKCiMjIyBJcyB0aGVyZSBvdmVybGFwIGJldHdlZW4gZ3JvdXBzPwpDaGFuZ2Ugb2YgdGhvc2UgdmFsdWVzIGFyZSBkaWZmZXJlbnQgaW4gaW5kaXZpZHVhbC4gVGhpcyBpbmZvbWF0aW9uIGlzIGFsc28gYWJsZSB0byBhc3N1bWVkIGJ5IGNvcnJlbGF0aW9uIHJlc3VsdC4gVGhvc2Ugc2NvcmVzIGhhcyBsZXNzIGNvcnJlbGF0ZWQgbWVhbnMsIGNoYW5nZSBvZiBzY29yZXMgYXJlIGRpZmZlcmVudCBhbW91bmcgaW5kaXZpZHVhbHMuCgpgYGB7cn0KbGlicmFyeShnZ1Zlbm5EaWFncmFtKQp4IDwtIGxpc3QoQ1ZfY3VyZT1DVl9oZWFkJFBhdG5yLCBJbnNfY3VyZT1JbnNfaGVhZCRQYXRuciwgTVZfY3VyZT1NVl90YWlsJFBhdG5yKQpnZ1Zlbm5EaWFncmFtKHgsIHNob3dfaW50ZXJzZWN0PVRSVUUpCmBgYAoKYGBge3J9CnggPC0gbGlzdChDVl9sZXNzPUNWX3RhaWwkUGF0bnIsIEluc19sZXNzPUluc190YWlsJFBhdG5yLCBNVl9sZXNzPU1WX2hlYWQkUGF0bnIpCmdnVmVubkRpYWdyYW0oeCwgc2hvd19pbnRlcnNlY3Q9VFJVRSkKYGBgCgoKIyMjIEluc3VsaW5lIHJlc3BvbmRlIGdlbmUgb2YgdGhvc2Ugc3ViZ3JvdXAuCkluc3VsaW5lIHJlc3BvbmQgc3ViZ3JvdXAgYmFzZWQgb24gSW5zdWxpbmUgbGV2ZWwuCgoKYGBge3J9CmNvbHNfdG9fc2VsZWN0IDwtIEluc19oZWFkJFBhdG5yCnNlbGVjdGVkX2NvbHMgPC0gcGhhc2UyLmZlbWFsZS5jb3VudHMgJT4lCiAgZHBseXI6OnNlbGVjdChjb250YWlucyhjb2xzX3RvX3NlbGVjdCkpCgpzZWxlY3RlZF9jb2xzCmBgYAoKCgpgYGB7cn0KbG9hZCgiL2hvbWUvcnN0dWRpby93b3JrL2RhdGEvRXhwcmVzc2lvblRhYmxlcy5SRGF0YSIpCmxvYWQoIi9ob21lL3JzdHVkaW8vd29yay9kYXRhL0Fubm90YXRpb24uUkRhdGEiKQpsb2FkKCIvaG9tZS9yc3R1ZGlvL3dvcmsvZGF0YS9Db2hvcnQuUkRhdGEiKQoKY29ob3J0XzIgPC0gY29ob3J0ICU+JQogIGRwbHlyOjpmaWx0ZXIoUGF0bnIgJWluJSBjb2xzX3RvX3NlbGVjdCkKCgpgYGAKCgoKYGBge3J9CmxpYnJhcnkoZWRnZVIpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBERSBhbmFseXNpcyBvZiBwYWlyZWQgc2FtcGxlcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpjb2hvcnQgPC0gY29ob3J0XzIKCklEczwtcGFzdGUoY29ob3J0JE9CX05PLGFzLmZhY3Rvcihjb2hvcnQkSURzKSxzZXA9Ii4iKQpDb25kaXRpb248LWNvaG9ydCRuZXdjb25kMgoKIyBkZXZpZGluZyBleHByZXNzaW9uIG1hdHJpeCB0byBzdWJncm91cApkZi5wYWlycyA8LSBzZWxlY3RlZF9jb2xzCgojIERFIEFuYWx5c2lzCnkgPC0gREdFTGlzdChjb3VudHM9ZGYucGFpcnMsZ3JvdXAgPSBDb25kaXRpb24pCmBgYAoKCmBgYHtyfQp5CmBgYAoKYGBge3J9CmRlc2lnbiA8LSBtb2RlbC5tYXRyaXgofjArQ29uZGl0aW9uK0lEcyxkYXRhPXkkc2FtcGxlcykKZGVzaWduIDwtIGRlc2lnblssIWdyZXBsKCJmMCIsIGNvbG5hbWVzKGRlc2lnbikpXQpkZXNpZ24gPC0gZGVzaWduWywgY29sU3VtcyhkZXNpZ24gIT0gMCkgPiAwXQoKYGBgCgoKYGBge1J9CmNvbG5hbWVzKGRlc2lnbik8LW1ha2UubmFtZXMoY29sbmFtZXMoZGVzaWduKSkKeSA8LSBjYWxjTm9ybUZhY3RvcnMoeSxub3JtLm1ldGhvZD0iUkxFIikKeSA8LSBlc3RpbWF0ZURpc3AoeSxkZXNpZ24pCmZpdCA8LSBnbG1GaXQoeSxkZXNpZ24scm9idXN0PVQpCgpteS5jb250cmFzdHM8LW1ha2VDb250cmFzdHMoCiAgSGl2c0YuT0I9Q29uZGl0aW9uT0JFU0UuaDAsCiAgSGl2c0YuUE9CPUNvbmRpdGlvbk9CRVNFLmgyLUNvbmRpdGlvbk9CRVNFLmYyLAogIGxldmVscz1kZXNpZ24pCmBgYAoKCmBgYHtyfQpjb250cmFzdHM8LWNvbG5hbWVzKG15LmNvbnRyYXN0cykKbXlmdW4gPC0gZnVuY3Rpb24oZmlsZXgpIHsKICBwcmludChmaWxleCkKICBscnQgPC0gZ2xtTFJUKGZpdCwgY29udHJhc3Q9bXkuY29udHJhc3RzWyxmaWxleF0pCiAgb3V0LnRvcD10b3BUYWdzKGxydCxuPUluZixhZGp1c3QubWV0aG9kPSdCSCcpCiAgb3V0LmFkaj1vdXQudG9wJHRhYmxlCiAgb3V0LmFkai4xPC1vdXQuYWRqCiAgaWYobnJvdyhvdXQuYWRqLjEpPT0wKXsKICAgIHJldHVybigpCiAgfWVsc2V7CiAgICBvdXQuYWRqLjEkQ29udHJhc3Q8LWZpbGV4CiAgICBvdXQuYWRqLjEkVEM8LXJvd25hbWVzKG91dC5hZGouMSkKICAgIG91dC5hZGouMSR1cGRvd248LWlmZWxzZShvdXQuYWRqLjEkbG9nRkM+MCwidXAiLCJkb3duIikKICAgIHJldHVybihvdXQuYWRqLjEpCiAgfQp9CmBgYAoKYGBge3J9CnkubGlzdDwtKGxhcHBseShjb250cmFzdHMsIG15ZnVuKSkKdGFiPC1kby5jYWxsKHJiaW5kLCB5Lmxpc3QpCnRhYiRTaWduPC1pZmVsc2UodGFiJEZEUjwwLjA1LCJzaWduIiwibm8iKQpyZXMuY291bnQgPC0gdGFibGUodGFiW3RhYiRTaWduPT0ic2lnbiIsXSRDb250cmFzdCx0YWJbdGFiJFNpZ249PSJzaWduIixdJHVwZG93biApCnJlcy5jb3VudCAKYGBgCgoKCiMjIyBDaGFnZSB0aGUgZGVzaWduCgplZGdlUiByZXN1bHQgYmVmb3JlIGhhcyA0NDEgZG93biByZWd1bGF0ZWQgZ2VuZS4gVGhpcyBpcyBub3Qgc2VlbXMgcmlnaHQuIEl0IGlzIGJlY2F1c2UgZGVzaWduIG1hdHJpeCBpcyBub3QgcHJvcGFyeSBzZXR0ZWQuCgpXaGF0IEkgd2FudCB0byBzZWUgaXMgZGlmZmVyZW50IGluc3VsaW5lIHJlc3BvbnNlIGdlbmUgYmV0d2VlbiArIGdyb3VwICh3ZWxsIGN1cmVkKSBhbmQgLSBncm91cCAobWlsZCBjdXJlZCkuCkl0IG1lYW5zLCBQT0IgaXMgbm90IG9uZSBidXQgc2VwYXJhdGVkIHRvIDIuCgotIE9CIChuPTYpOiBPQl9mIHZzIE9CX2hpCi0gUE9CKyAobj02KTogUE9CK19mIHZzIFBPQitfaGkKLSBQT0ItIChuPTYpOiBQT0ItX2YgdnMgUE9CLV9oaQotIE5PIChuPTYpOiBOT19mIHZzIE5PX2hpCgpOTyB3aWxsIGJlIGFsc28gbWF0Y2hlZCB3aXRoIEFnZSwgTS12YWx1ZSBhbmQgQk1JIG1lYW4gb2YgUE9CKyBhbmQgUE9CLS4KCmBgYHtyfQpBZ2VfZGYgPC0gZGF0YS5mcmFtZShQT0JwID0gUE9CcCRBZ2UsIFBPQm0gPSBQT0JtJEFnZSkKZ2dwbG90KGRhdGEgPSBBZ2VfZGYpICsKICBnZW9tX3BvaW50KCkKICAKYGBgCgoKRmlyc3QgZ2V0IG1hdGNoZWQgTk8gZ3JvdXBzLgpgYGB7cn0KIyBnZXQgTk8gd2l0aCBtYXRjaGVkIGRpc3RyaWJ1dGlvbiB3aXRoIFBPQisgYW5kIFBPQi0Kc2V0LnNlZWQoMTIzKQoKUE9CcCA8LSBjbGluaWMgJT4lIAogICAgZHBseXI6OmZpbHRlcihQYXRuciAlaW4lIEluc19oZWFkJFBhdG5yKQogIApQT0JtIDwtIGNsaW5pYyAlPiUgCiAgICBkcGx5cjo6ZmlsdGVyKFBhdG5yICVpbiUgSW5zX3RhaWwkUGF0bnIpCiAgCk5PcyA8LSBjbGluaWMgJT4lIGRwbHlyOjpmaWx0ZXIoVHlwZSA9PSJOTyIpCnNlbGVjdF9OTyA8LSBOT3MgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1heChQT0JwJEFnZSkgPiBBZ2UsICBBZ2U+IG1pbihQT0JwJEFnZSkpICU+JQogICAgZHBseXI6OmZpbHRlcihtYXgoUE9CcCRCTUkpID4gQk1JLCAgQk1JPiBtaW4oUE9CcCRCTUkpKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobWF4KFBPQnAkTV92X3JkZV82MF8xMjApID4gTV92X3JkZV82MF8xMjAsICBNX3ZfcmRlXzYwXzEyMD4gbWluKFBPQnAkTV92X3JkZV82MF8xMjApKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoUGF0bnIgJWluJSBjb2hvcnQkUGF0bnIpICU+JQogICAgc2FtcGxlX24oNikKYGBgCgoKQWxzbyBzZWxlY3QgNiBvZiBPQiAoZWFjaCAzIGZyb20gUE9CKywgUE9CLSBtYXRjaGVkIE9CKS4KYGBge3J9CgpPQnBfSUQgPC0gc2FtcGxlKEluc19oZWFkJFBhdG5yLCAzKQpPQm1fSUQgPC0gc2FtcGxlKEluc190YWlsJFBhdG5yLCAzKQpPQl9JRCA8LSBjKE9CcF9JRCwgT0JtX0lEKQpgYGAKCgpgYGB7cn0KIyBEYXRhIHRvIHJ1biBlZGdlUgpwcmludChPQl9JRCkgIyBPQiBncm91cApwcmludChzZWxlY3RfTk8kUGF0bnIpICMgTk8gZ3JvdXAKcHJpbnQoSW5zX2hlYWQkUGF0bnIpICMgUE9CKyBncm91cApwcmludChJbnNfdGFpbCRQYXRucikgIyBQT0ItIGdyb3VwCgpgYGAKCmBgYHtyfQojIGNvbHVtbiBuYW1lcyBpbiB0aGUgY291bnQgbWF0cml4Ck9CX2NvbCA8LSBjb2hvcnQgJT4lCiAgZHBseXI6OmZpbHRlcihPQl9OT19QT0IgPT0gIk9CIikgJT4lCiAgZHBseXI6OmZpbHRlcihQYXRuciAlaW4lIE9CX0lEKSAlPiUKICBzZWxlY3QoQ29uZCkKCgpOT19jb2wgPC0gY29ob3J0ICU+JQogIGRwbHlyOjpmaWx0ZXIoT0JfTk9fUE9CID09ICJOTyIpICU+JQogIGRwbHlyOjpmaWx0ZXIoUGF0bnIgJWluJSBzZWxlY3RfTk8kUGF0bnIpICU+JQogIHNlbGVjdChDb25kKQoKUE9CcF9jb2wgPC0gY29ob3J0ICU+JQogIGRwbHlyOjpmaWx0ZXIoT0JfTk9fUE9CID09ICJQT0IiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKFBhdG5yICVpbiUgSW5zX2hlYWQkUGF0bnIpICU+JQogIHNlbGVjdChDb25kKQoKClBPQm1fY29sIDwtIGNvaG9ydCAlPiUKICBkcGx5cjo6ZmlsdGVyKE9CX05PX1BPQiA9PSAiUE9CIikgJT4lCiAgZHBseXI6OmZpbHRlcihQYXRuciAlaW4lIEluc190YWlsJFBhdG5yKSAlPiUKICBzZWxlY3QoQ29uZCkKCmBgYCAKCgpgYGB7cn0Kc2VsZWN0X3NhbXBsZSA8LSBjKE9CX2NvbCRDb25kLCBOT19jb2wkQ29uZCwgUE9CcF9jb2wkQ29uZCwgUE9CbV9jb2wkQ29uZCkKIyBzZWxlY3Qgc2FtcGxlcyB0byB1c2UKZGYucGFpcnMgPC0gcGhhc2UyLmZlbWFsZS5jb3VudHMgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QoY29udGFpbnMoc2VsZWN0X3NhbXBsZSkpCgoKbG9hZCgiL2hvbWUvcnN0dWRpby93b3JrL2RhdGEvQ29ob3J0LlJEYXRhIikKIyBzdWJzZXQgY29ob3J0IGZpbGUKY29ob3J0XzIgPC0gY29ob3J0ICU+JQogIGRwbHlyOjpmaWx0ZXIoQ29uZCAlaW4lIHNlbGVjdF9zYW1wbGUpCgpjb2hvcnQgPC0gY29ob3J0XzIKY29ob3J0JGNvbmRpdGlvbiA8LSBpZmVsc2UoY29ob3J0JENvbmQgJWluJSBPQl9jb2wkQ29uZCwgIk9CIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShjb2hvcnQkQ29uZCAlaW4lIE5PX2NvbCRDb25kLCAiTk8iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShjb2hvcnQkQ29uZCAlaW4lIFBPQnBfY29sJENvbmQsICJQT0JwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoY29ob3J0JENvbmQgJWluJSBQT0JtX2NvbCRDb25kLCAiUE9CbSIsIk5BIikpKSkKCmNvaG9ydCA8LSBjb2hvcnQgJT4lIAogIG11dGF0ZSh0aW1lID0gc3RyX3N1YihDb25kLC0yLC0xKSkKY29ob3J0IDwtIGNvaG9ydCAlPiUgCiAgbXV0YXRlKGNvbmRpdGlvbjIgPSBwYXN0ZShjb2hvcnQkY29uZGl0aW9uLCBjb2hvcnQkdGltZSxzZXA9Ii4iKSkKCklEczwtcGFzdGUoY29ob3J0JE9CX05PLGFzLmZhY3Rvcihjb2hvcnQkSURzKSxzZXA9Ii4iKSAjIHB1dCBzYW1lIElEIGZvciBzYW1lIGluZGl2aXN1YWwKQ29uZGl0aW9uPC1jb2hvcnQkY29uZGl0aW9uMgpgYGAKCgpgYGB7cn0KIyBERSBBbmFseXNpcwp5IDwtIERHRUxpc3QoY291bnRzPWRmLnBhaXJzLGdyb3VwID0gQ29uZGl0aW9uKQoKYGBgCgpgYGB7cn0KIyBkZXNpZ246IENvbmRpdGlvbiAoT0IsTk8sUE9CcCxQT0JtKSBhbmQgaW5kaXZpc3VhbApkZXNpZ248LW1vZGVsLm1hdHJpeCh+MCtDb25kaXRpb24rSURzLGRhdGE9eSRzYW1wbGVzKQpgYGAKCmBgYHtyfQpkZXNpZ24gPC0gZGVzaWduWywhZ3JlcGwoImYwIiwgY29sbmFtZXMoZGVzaWduKSldCmRlc2lnbjwtZGVzaWduWywgY29sU3VtcyhkZXNpZ24gIT0gMCkgPiAwXQpjb2xuYW1lcyhkZXNpZ24pPC1tYWtlLm5hbWVzKGNvbG5hbWVzKGRlc2lnbikpCnkgPC0gY2FsY05vcm1GYWN0b3JzKHksbm9ybS5tZXRob2Q9IlJMRSIpCgpgYGAKCmBgYHtyfQp5IDwtIGVzdGltYXRlRGlzcCh5LGRlc2lnbikKZml0IDwtIGdsbUZpdCh5LGRlc2lnbixyb2J1c3Q9VCkKYGBgCgoKYGBge3J9Cm15LmNvbnRyYXN0czwtbWFrZUNvbnRyYXN0cygKICBIaXZzRi5OTz1Db25kaXRpb25OTy5oMCwKICBIaXZzRi5PQj1Db25kaXRpb25PQi5oMCwKICBIaXZzRi5QT0JwPUNvbmRpdGlvblBPQnAuaDItQ29uZGl0aW9uUE9CcC5mMiwKICBIaXZzRi5QT0JtPUNvbmRpdGlvblBPQm0uaDItQ29uZGl0aW9uUE9CbS5mMiwKICBsZXZlbHM9ZGVzaWduKQoKY29udHJhc3RzPC1jb2xuYW1lcyhteS5jb250cmFzdHMpCm15ZnVuIDwtIGZ1bmN0aW9uKGZpbGV4KSB7CiAgcHJpbnQoZmlsZXgpCiAgbHJ0IDwtIGdsbUxSVChmaXQsIGNvbnRyYXN0PW15LmNvbnRyYXN0c1ssZmlsZXhdKQogIG91dC50b3A9dG9wVGFncyhscnQsbj1JbmYsYWRqdXN0Lm1ldGhvZD0nQkgnKQogIG91dC5hZGo9b3V0LnRvcCR0YWJsZQogIG91dC5hZGouMTwtb3V0LmFkagogIGlmKG5yb3cob3V0LmFkai4xKT09MCl7CiAgICByZXR1cm4oKQogIH1lbHNlewogICAgb3V0LmFkai4xJENvbnRyYXN0PC1maWxleAogICAgb3V0LmFkai4xJFRDPC1yb3duYW1lcyhvdXQuYWRqLjEpCiAgICBvdXQuYWRqLjEkdXBkb3duPC1pZmVsc2Uob3V0LmFkai4xJGxvZ0ZDPjAsInVwIiwiZG93biIpCiAgICByZXR1cm4ob3V0LmFkai4xKQogIH0KfQoKeS5saXN0PC0obGFwcGx5KGNvbnRyYXN0cywgbXlmdW4pKQp0YWI8LWRvLmNhbGwocmJpbmQsIHkubGlzdCkKdGFiJFNpZ248LWlmZWxzZSh0YWIkRkRSPDAuMDUsInNpZ24iLCJubyIpCnJlcy5jb3VudCA8LSB0YWJsZSh0YWJbdGFiJFNpZ249PSJzaWduIixdJENvbnRyYXN0LHRhYlt0YWIkU2lnbj09InNpZ24iLF0kdXBkb3duICkKcmVzLmNvdW50IAoKc2F2ZSh0YWIsZmlsZT0iL2hvbWUvcnN0dWRpby93b3JrL2RhdGEvT0I2X05PNl9QT0JwNl9QT0JtNi5SRGF0YSIpCgpgYGAKUmVtb3ZlIE5PCgpgYGB7cn0Kc2VsZWN0X3NhbXBsZSA8LSBjKE9CX2NvbCRDb25kLCBQT0JwX2NvbCRDb25kLCBQT0JtX2NvbCRDb25kKQojIHNlbGVjdCBzYW1wbGVzIHRvIHVzZQpkZi5wYWlycyA8LSBwaGFzZTIuZmVtYWxlLmNvdW50cyAlPiUgCiAgICAgZHBseXI6OnNlbGVjdChjb250YWlucyhzZWxlY3Rfc2FtcGxlKSkKCgpsb2FkKCIvaG9tZS9yc3R1ZGlvL3dvcmsvZGF0YS9Db2hvcnQuUkRhdGEiKQojIHN1YnNldCBjb2hvcnQgZmlsZQpjb2hvcnRfMiA8LSBjb2hvcnQgJT4lCiAgZHBseXI6OmZpbHRlcihDb25kICVpbiUgc2VsZWN0X3NhbXBsZSkKCmNvaG9ydCA8LSBjb2hvcnRfMgpjb2hvcnQkY29uZGl0aW9uIDwtIGlmZWxzZShjb2hvcnQkQ29uZCAlaW4lIE9CX2NvbCRDb25kLCAiT0IiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShjb2hvcnQkQ29uZCAlaW4lIFBPQnBfY29sJENvbmQsICJQT0JwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoY29ob3J0JENvbmQgJWluJSBQT0JtX2NvbCRDb25kLCAiUE9CbSIsIk5BIikpKQoKY29ob3J0IDwtIGNvaG9ydCAlPiUgCiAgbXV0YXRlKHRpbWUgPSBzdHJfc3ViKENvbmQsLTIsLTEpKQpjb2hvcnQgPC0gY29ob3J0ICU+JSAKICBtdXRhdGUoY29uZGl0aW9uMiA9IHBhc3RlKGNvaG9ydCRjb25kaXRpb24sIGNvaG9ydCR0aW1lLHNlcD0iLiIpKQoKSURzPC1wYXN0ZShjb2hvcnQkT0JfTk8sYXMuZmFjdG9yKGNvaG9ydCRJRHMpLHNlcD0iLiIpICMgcHV0IHNhbWUgSUQgZm9yIHNhbWUgaW5kaXZpc3VhbApDb25kaXRpb248LWNvaG9ydCRjb25kaXRpb24yCgoKeSA8LSBER0VMaXN0KGNvdW50cz1kZi5wYWlycyxncm91cCA9IENvbmRpdGlvbikKZGVzaWduPC1tb2RlbC5tYXRyaXgofjArQ29uZGl0aW9uK0lEcyxkYXRhPXkkc2FtcGxlcykKZGVzaWduIDwtIGRlc2lnblssIWdyZXBsKCJmMCIsIGNvbG5hbWVzKGRlc2lnbikpXQpkZXNpZ248LWRlc2lnblssIGNvbFN1bXMoZGVzaWduICE9IDApID4gMF0KY29sbmFtZXMoZGVzaWduKTwtbWFrZS5uYW1lcyhjb2xuYW1lcyhkZXNpZ24pKQp5IDwtIGNhbGNOb3JtRmFjdG9ycyh5LG5vcm0ubWV0aG9kPSJSTEUiKQoKeSA8LSBlc3RpbWF0ZURpc3AoeSxkZXNpZ24pCmZpdCA8LSBnbG1GaXQoeSxkZXNpZ24scm9idXN0PVQpCgpteS5jb250cmFzdHM8LW1ha2VDb250cmFzdHMoCiAgSGl2c0YuT0I9Q29uZGl0aW9uT0IuaDAsCiAgSGl2c0YuUE9CcD1Db25kaXRpb25QT0JwLmgyLUNvbmRpdGlvblBPQnAuZjIsCiAgSGl2c0YuUE9CbT1Db25kaXRpb25QT0JtLmgyLUNvbmRpdGlvblBPQm0uZjIsCiAgbGV2ZWxzPWRlc2lnbikKCmNvbnRyYXN0czwtY29sbmFtZXMobXkuY29udHJhc3RzKQpteWZ1biA8LSBmdW5jdGlvbihmaWxleCkgewogIHByaW50KGZpbGV4KQogIGxydCA8LSBnbG1MUlQoZml0LCBjb250cmFzdD1teS5jb250cmFzdHNbLGZpbGV4XSkKICBvdXQudG9wPXRvcFRhZ3MobHJ0LG49SW5mLGFkanVzdC5tZXRob2Q9J0JIJykKICBvdXQuYWRqPW91dC50b3AkdGFibGUKICBvdXQuYWRqLjE8LW91dC5hZGoKICBpZihucm93KG91dC5hZGouMSk9PTApewogICAgcmV0dXJuKCkKICB9ZWxzZXsKICAgIG91dC5hZGouMSRDb250cmFzdDwtZmlsZXgKICAgIG91dC5hZGouMSRUQzwtcm93bmFtZXMob3V0LmFkai4xKQogICAgb3V0LmFkai4xJHVwZG93bjwtaWZlbHNlKG91dC5hZGouMSRsb2dGQz4wLCJ1cCIsImRvd24iKQogICAgcmV0dXJuKG91dC5hZGouMSkKICB9Cn0KCnkubGlzdDwtKGxhcHBseShjb250cmFzdHMsIG15ZnVuKSkKdGFiPC1kby5jYWxsKHJiaW5kLCB5Lmxpc3QpCnRhYiRTaWduPC1pZmVsc2UodGFiJEZEUjwwLjA1LCJzaWduIiwibm8iKQpyZXMuY291bnQgPC0gdGFibGUodGFiW3RhYiRTaWduPT0ic2lnbiIsXSRDb250cmFzdCx0YWJbdGFiJFNpZ249PSJzaWduIixdJHVwZG93biApCnJlcy5jb3VudCAKCnNhdmUodGFiLGZpbGU9Ii9ob21lL3JzdHVkaW8vd29yay9kYXRhL09CNl9QT0JwNl9QT0JtNi5SRGF0YSIpCmBgYAo=